Running a MySQL database in a Docker Container

Comments 0

Share to social media

Relational databases provide a structured approach for storing and organizing large volumes of data into tables consisting of rows for records, and columns for attributes. They use primary keys which are unique identifiers for records and foreign keys, to establish well defined relationships between tables.

These databases are widely used since they are reliable, consistent, and highly adaptable to various applications. They also provide complex database queries and operations capabilities using a structured query language (SQL). They are backed up with a strong and mature ecosystem; with extensive tooling and community support.

MySQL, PostgreSQL, MariaDB, Microsoft SQL Server, and Oracle databases are all examples of relational databases. You can run them within virtual machines or Docker containers. This article, on the other hand, will include the steps to run MySQL, which is one of the widely used relational databases in a Docker container.

Why run a Relational Database with Docker

You might be wondering why one would run a complex system like a relational database in a Docker container in the first place, well hang on. There is no doubt that containers are designed primarily for stateless applications. That is to say, containers are ephemeral in nature and without proper configuration, the operational status of a container could be disrupted, resulting in data loss.

Databases, on the other hand, are stateful and require persistent storage to run optimally, especially in times of restarts and even crashes. Yes, Docker volumes are designed to persist data beyond the lifecycle of a container; however, running a relational database is fine for development and testing purposes but is not recommended for production. Instead, for production environments you should run them on standalone servers, managed database services like AWS RDS or Azure SQL database, or store data on an external volume like cloud storage or block storage (AWS EBS, Azure managed Disks, etc).

Here are some of the reasons why you might need to run a relational database with Docker in detail:

  • Isolation and reproducibility: Docker containers provide you with the ability to run applications in a completely isolated environment; to test new database features, configurations, or updates like security parameters, user roles, authentication, and many more.
  • Microservice Decoupling: To implement a microservice architecture whereby you can ensure data isolation to one service’s database without affecting the database of a different service.
  • Try and Error: To experiment with different database configurations on the same machine using multiple database instances. You can test different database engines or different versions of the same engine.

In this article, I will show you how to get MySQL up and running, and show you how to set it up and use MySQL On Docker for your non-production environments.

Prerequisites

To follow along, you are required to have Docker engine installed on your machine. This tutorial uses the latest versions of Docker (28.0.1) on an Ubuntu 24.04 LTS server from when this piece was written. There may be subtle differences as time passes, and if you are using a different operating system.

Pulling the Official MySQL Docker Image

Whether it’s a relational or non-relational database, or something else entirely, you need to pull a base image if you would like to run anything with Docker. In the case of a relational database like MySQL, the official Docker image from DockerHub is maintained by the MySQL team. It is pre-configured with all dependencies to run MySQL effectively. It is also properly documented to help you quickly install and make configurations for MySQL on your host system.

Execute the following command to pull the official MySQL docker image from DockerHub:

This should pull the latest version from DockerHub. Once the MySQL image has been pulled successfully, you are expected to have the following output:

Confirm that the MySQL image is available on your machine using the following command:

You are good to go if it is listed among the Docker images available on your machine:

Creating a Docker Network

Networks in Docker represent a communication environment that allows containers to communicate and interact with each other in a secure manner. Regardless of what kind of image or application you are running with Docker, you should always consider creating a Docker network to ensure isolated communication between your containers.

Docker supports seven network drivers by default, you can find them on the official Docker documentation. If other network drivers are not set, the bridge network driver is the default. Additionally, a Docker network is automatically created when you run a Docker image as a container. In our case, we will create a custom docker network using the bridge network driver and give it a generic name mysql-net with the following command:

Confirm that mysql-net is listed amongst the list of Docker networks on your machine:

You should see it listed in the list like so:

Run the MySQL image as a Docker container, connect to the mysql-net network and initialize the MySQL database with a root password. If you are going to use this instance for any work, use a proper password:

Take note, you can also initialize the MySQL database with two more authentication-related environment variables. For example:

  • MYSQL_ALLOW_EMPTY_PASSWORD: This environment variable allows the MySQL database to start without a root password; which is not proper for production environments.
  • MYSQL_RANDOM_ROOT_PASSWORD: This environment variable allows the MySQL database to start with a random root password and then print it in the logs.

For our case, our current setup will suffice. Verify that the MySQL database is up and running using the command below:

You should have the output similar to the following:

Dates, times and the CONTAINER ID value will be different, but the output should look very similar.

Checking for Data Persistence

Again, containers are stateless, a database that runs in a container risks losing all its data if the container is deleted whether on purpose or unexpectedly. Therefore, it is mandatory to use data persistence mechanisms to ensure that data is retained even if the container stops or is removed. In this case, you’ll consider common persistence mechanisms like Docker volumes or bind mounts.

To begin, let’s confirm data is not persistent when a container is deleted. Go into the MySQL container using the following command, replacing <container-id> with your MySQL container ID:

For example, in my case it would be:

Input your password and you should get a prompt to enter MySQL commands. So to start, we will create a database named: book_hub:

You should see messages after most commands. Like after this one you will see “Query OK, 1 row affected” for example. Next, select the book_hub database:

Create a table Publishers in the book_hub database:

Next, add some data into the Publishers table, the following values:

Confirm that all values have been inserted (in addition to the message you will have received):

You should have the following output:

Exit out of the MySQL container and exec back into the MySQL container:

The aim here is to check if the data is still available even after exiting out of the MySQL container.

Now select the book_hub database and view the publishers table with the following commands:

You should see the contents of the Publisher table outputted to you which is expected. This simply means that exiting out of the MySQL container doesn’t incur data loss. To simulate data loss, you’ll need to remove the MySQL container and run a new one.

Stop and remove the MySQL container:

Note: While containers do not lose data when you exit it, or even if you restart the container (which you can do with the Docker start and stop commands), being able to destroy and recreate the container makes it easier to test new features or updates without affecting the data you have stored. Some care may need to be taken to use a compatible version of MySQL (or any tool you are using), and it may be best to make a copy of your data before attaching that new container.

Next, Initialize a new MySQL instance:

Then connect to it by finding the container Id:

Then connecting to it by using the container id.:

Input your password and attempt to use the book_hub database:

You should see an error message similar to the one below:

ERROR 1049 (42000): Unknown database ‘book_hub’

This is expected because the book_hub database and its data were stored inside the previous container. Since we removed that container, all its data was lost.

Configuring Data Persistence with Docker Volumes

Docker volumes allow you to store data outside of Docker containers. With Docker volumes data can be maintained across container lifecycles so you don’t have to worry about data loss in time of container crashes or disruptions.

To begin, you must run the MySQL container with a volume. You can create a volume separately and then attach it to the MySQL container, or you create one on the go while running the MySQL container. Use the following command to run the MySQL container with a volume called mysql-data:

Confirm the MySQL container is running and get its container ID:

Go into the MySQL container:

Create a database with the name book_hub and select it as your database. Follow the same process as before using these commands:

Now, view the Author data;

And just like earlier in the article, you should see the following output:

Exit the MySQL container by typing exit and proceed to delete the MySQL container using the following command:

Confirm that the Docker volume mysql-data still exists:

Because the MySQL container was removed doesn’t mean the Docker volume is also, you should see it listed among other Docker volumes present on your machine:

Now spin up a new container and attach the volume (mysql-data) to it:

Connect to the MySQL container (again finding the container id with docker ps):

Confirm that the book_hub database exists by attempting to select it:

If you have the following output, you have successfully persisted data with Docker volumes.

This shows that the database exists:

This is also true for all tables in the book_hub database, for example, view the Author table:

Should return:

So now we have part of the picture.

Configuring Data Persistence with Bind Mounts

Bind mounts can also ensure data persistence; especially when you want your container to have direct access to host files. While slower due to direct filesystem access, you can persist data as we have done with Docker volumes.

To use bind mounts, you must first create the directory on your host machine that you want to mount into the container. If the directory already exists you’ll need to mount the host on the go while running the MySQL container. Keep in mind that bind mounts use your host filesystem and are not managed by Docker.

Create a directory mysql-data on the host with the following command:

Run the MySQL container and mount the host directory inside the MySQL container:

Check that the MySQL container is running:

Go inside the MySQL container and create a database :

Enter the root password and then execute the following commands sequentially:

Remove the MySQL container:

Rerun the MySQL container:

Check if the testdb still exists by running the below command:

Then execute:

You should see the testdb database listed among all available databases:

Then you should see:

This shows that data has persisted, so you can now drop and recreate the container, referencing the Bind Mount, and the data you expect will be there.

Conclusion

You can run any application in a containerized environment with Docker, including a relational database like MySQL, and have an understanding how to keep data persisted, even after a reboot.

In this article, you have seen how to run a MySQL database in Docker, configure data persistence using Docker volumes and bind mounts and most of all, set up replication, by deploying master and replica containers on the same Docker network.

Article tags

Load comments

About the author

Mercy Bassey

See Profile

Mercy is a talented technical writer and programmer with deep knowledge of various technologies. She focuses on cloud computing, software development, DevOps/IT, and containerization, and she finds joy in creating documentation, tutorials, and guides for both beginners and advanced technology enthusiasts.